<HTML>
<HEAD>
<TITLE>Stephen Riehm's Bracketing macro system for Vim</TITLE>
</HEAD>

<BODY>
<H1>Stephen Riehm's Bracketing macro system for Vim</H1>
Last Updated: Wed 29 Jul, 98
<HR>

<P>The following description is a little long, for which I
apologise, but I have great difficulty describing these macros,
as there is nothing around to compare it with. Please be patient!
I can't live without these macros, and I know a few other people
who have made the effort, and who also find them extremely useful.
</P>

<DL>
    <DT><B>Assumption:</B>
    <DD>
    Whenever you type a bracket or quote, you normally want the
    matching bracket or quote as well, and if you forget it, then
    you're going to have problems.
    <P>
    <DT><B>Solution:</B>
    <DD>
    Whenever you type a bracket or quote, have the editor type the matching
    one for you. (P.S.: mapping these macros directly to the
    characters themselves is a bad idea - use macro names which aren't
    going to be confused with normal text. (think about what happens
    when you cut'n'paste, or things like wanting to actually type a
    singles bracket, ie: <KBD>if( x == "(" )</KBD>))
</DL>

<H2>The system:</H2>
<P>
Moving "around" brackets and quotes is a pain, so each of the
bracketing macros leaves a special marker just after the
closing bracket, so that you can easily jump out of where you
are. This can be thought of as a mini-form system. The macros
insert little forms into your text or code, and you then
simply tab your way through the form and fill out the missing
bits. (You can also very easily create form-like templates,
and use the same macros to help you fill them out)
</P>

<H2>Two parts:</H2>
<P>
The system has two parts, the macros for creating the mini
forms, and the special characters and one macro for jumping
around in those forms. Both parts are needed for this system
to work.
</P>

<H1>The Macros:</H1>
<P>
I have found the Meta/Alt Key to be very useful, as vi doesn't
use them by default, and they very nicely overlap ALL keyboard
characters. The only problem is recognising them once they've
been typed, which is why I have commented each macro using the
M- notation. The following maps can be used in insert mode
when writing new text, or in visual mode when modifying
existing text. In visual mode, you highlight the text you want
to "wrap" and then use the appropriate macro, in insert mode,
you type the macro and then fill in the middle.
</P>

<CENTER>
<TABLE BORDER=2 CELLPADDING=5 ALIGN=CENTER>
<THEAD>
<TR>
    <TH>Macro in <KBD>macros</KBD>
    <TH>Macro in <KBD>macros.no-meta</KBD>
    <TH>Description
    <TH>Example
</TR>
</THEAD>
<TBODY>

<TR>
    <TD><B>DEL</B>
    <TD><B>DEL</B>
    <TD>Jump to next marker
    <TD>(the marker is replaced by the cursor)
</TR>

<TR>
    <TD><B>M-'</B>
    <TD><B>''</B>
    <TD>Single quotes
    <TD><B>'</B><KBD>text</KBD><B>'</B>
</TR>

<TR>
    <TD><B>M-"</B>
    <TD><B>""</B>
    <TD>Double quotes
    <TD><B>"</B><KBD>text</KBD><B>"</B>
</TR>

<TR>
    <TD><B>M-`</B>
    <TD><B>``</B>
    <TD>Back-quotes
    <TD><B>`</B><KBD>text</KBD><B>`</B>
</TR>

<TR>
    <TD><B>M-(</B>
    <TD><B>((</B>
    <TD>Braces, no padding
    <TD><B>(</B><KBD>text</KBD><B>)</B>
</TR>

<TR>
    <TD><B>M-)</B>
    <TD><B>))</B>
    <TD>Braces, with padding
    <TD><B>( </B><KBD>text</KBD><B> )</B>
</TR>

<TR>
    <TD><B>M-[</B>
    <TD><B>[[</B>
    <TD>Brackets, no padding
    <TD><B>[</B><KBD>text</KBD><B>]</B>
</TR>

<TR>
    <TD><B>M-]</B>
    <TD><B>]]</B>
    <TD>Brackets, with padding
    <TD><B>[ </B><KBD>text</KBD><B> ]</B>
</TR>

<TR>
    <TD><B>M-{</B>
    <TD><B>{{</B>
    <TD>Curlies, no padding
    <TD><B>{</B><KBD>text</KBD><B>}</B>
</TR>

<TR>
    <TD><B>M-}</B>
    <TD><B>}}</B>
    <TD>A new block
    <TD>
<!-- it would be nice if these bolded characters would work :-( --!>
<PRE>
{
    text
}
</PRE>
</TR>

<TR>
    <TD><B>M-<</B>
    <TD><B><<</B>
    <TD>Angle brackets, no padding
    <TD><B><</B><KBD>text</KBD><B>></B>
</TR>

<TR>
    <TD><B>M-></B>
    <TD><B>>></B>
    <TD>Angle brackets, with padding
    <TD><B>< </B><KBD>text</KBD><B> ></B>
</TR>

<TR>
    <TD><B>M-\</B>
    <TD><B>)}</B>
    <TD>short cut for <B>M-)M-}</B>
    <TD>
<PRE>
( text1 )
{
    text2
}
</PRE>
</TR>

<TR>
    <TD><B>M-h</B>
    <TD><I>not available</I>
    <TD>use the last typed word as a HTML tag, in this example,
    <KBD>blockquote</KBD><B>M-h</B> was typed.
    <TD><B>&lt;BLOCKQUOTE&gt;</B><KBD>text</KBD><B>&lt;/BLOCKQUOTE&gt;</B>
</TR>

<TR>
    <TD><B>M-r</B>
    <TD><I>not available</I>
    <TD>Enter a URL tag
    <TD><B>&lt;A HREF="</B><KBD>URL</KBD><B>"&gt;</B><KBD>text</KBD><B>&lt;/A&gt;</B>
</TR>

<TR>
    <TD><B>M-n</B>
    <TD><I>not available</I>
    <TD>Set a HTML named index, for use with <KBD>&lt;A HREF="#name"&gt;&lt;/A&gt;</KBD>
    <TD><B>&lt;A NAME="</B><KBD>NAME</KBD><B>"&gt;</B><KBD>text</KBD><B>&lt;/A&gt;</B>
</TR>

<TR>
    <TD><B>M-fM-b</B>
    <TD><I>not available</I>
    <TD>NROFF macro for Bold text
    <TD><B>\fB</B><KBD>text</KBD><B>\fP</B>
</TR>

<TR>
    <TD><B>M-fM-i</B>
    <TD><I>not available</I>
    <TD>NROFF macro for Italic text
    <TD><B>\fI</B><KBD>text</KBD><B>\fP</B>
</TR>

</TBODY>
</TABLE>
</CENTER>

<H1>So what have I gained?</H1>
<P>
The real advantage comes when you are writing code, with lots of
nesting. Here's a step by step example of a slightly complicated if
statement in a shell script: (the cursor position is shown with an <B>_</B>
(underscore))
</P>


<CENTER>
<TABLE BORDER=2 CELLPADDING=5 ALIGN=CENTER>
<THEAD>
<TR>
    <TH><B>You type:</B>
    <TH><B>You get:</B>
</TR>
</THEAD>
<TBODY>

<TR>
    <TD>if <B>&lt;M-[&gt;</B><B>&lt;M-]&gt;</B>
    <TD>if [[ <B>_</B> ]<B>&laquo;&raquo;</B>]<B>&laquo;&raquo;</B>
</TR>

<TR>
    <TD>-f <B>&lt;M-"&gt;</B>
    <TD>if [[ -f "<B>_</B>"<B>&laquo;&raquo;</B> ]<B>&laquo;&raquo;</B>]<B>&laquo;&raquo;</B>
</TR>

<TR>
    <TD>$file<B>&lt;Del&gt;</B>
    <TD>if [[ -f "$file"<B>_</B> ]<B>&laquo;&raquo;</B>]<B>&laquo;&raquo;</B>
</TR>

<TR>
    <TD> && <B>&lt;M-"&gt;</B>
    <TD>if [[ -f "$file" && "<B>_</B>"<B>&laquo;&raquo;</B> ]<B>&laquo;&raquo;</B>]<B>&laquo;&raquo;</B>
</TR>

<TR>
    <TD>$<B>&lt;M-{&gt;</B>
    <TD>if [[ -f "$file" && "${<B>_</B>}<B>&laquo;&raquo;</B>"<B>&laquo;&raquo;</B> ]<B>&laquo;&raquo;</B>]<B>&laquo;&raquo;</B>
</TR>

<TR>
    <TD>name<B>&lt;Del&gt;</B><B>&lt;Del&gt;</B>
    <TD>if [[ -f "$file" && "${name}<B>_</B>"<B>&laquo;&raquo;</B> ]<B>&laquo;&raquo;</B>]<B>&laquo;&raquo;</B>
</TR>

<TR>
    <TD> != <B>&lt;M-"&gt;</B>
    <TD>if [[ -f "$file" && "${name}" != "<B>_</B>"<B>&laquo;&raquo;</B> ]<B>&laquo;&raquo;</B>]<B>&laquo;&raquo;</B>
</TR>

<TR>
    <TD>Fred<B>&lt;Del&gt;</B><B>&lt;Del&gt;</B><B>&lt;Del&gt;</B>
    <TD>if [[ -f "$file" && "${name}" != "Fred" ]]<B>_</B>
</TR>


</TBODY>
</TABLE>
</CENTER>

<P>
In typing this example, I didn't have to match any brackets,
quotes or braces.
</P>

<P>
In a similar example, if you want a C-like "if" statement, simply
type <KBD>if <B>&lt;M-\&gt;</B></KBD>, and you get:
</P>

<PRE><KBD>
    if ( <B>_</B> )
    {
	<B>&laquo;&raquo;</B>
    }<B>&laquo;&raquo;</B>
</KBD></PRE>

<P>
The macro leaves your cursor at the <B>_</B>, in insert
mode (so you can simply keep typing), and then you just need to hit
<B>&lt;DEL&gt;</B> to jump into the if block, and <B>&lt;DEL&gt;</B>
again gets you out of the if block. You can then either hit
<B>&lt;ESC&gt;</B> to do something else, or <B>&lt;RETURN&gt;</B> to
start typing the next statements.
</P>

<H2>Did you say <EM>"Modeless"</EM>?</H2>
<P>
Well, almost :-)
</P>

<P>
Most of these macros are defined for insert mode and
visual mode. For example: you can insert a new set of quotes when
in insert mode by using the <B>&lt;M-"&gt;</B> macro, or you can
quote <EM>after the fact</EM> by selecting the words you want quoted in
visual mode, and then hitting <B>&lt;M-"&gt;</B>. (it even works on
multiple lines!)
</P>

<P>
The <B>&lt;Del&gt;</B> macro can be used in command mode or in insert
mode, either way, you jump to the next marker and are left in insert
mode. You can bounce on the <B>&lt;Del&gt;</B> key to clean up any
left over markers - when it beeps (leaving you in command mode!) there
are no more markers in the file (do you have wrapscan turned on
too? If not - you might need to go to the top of the file and try
again to be certain)
</P>

<H1>M-} is different!</H1>
<P>
The <B>&lt;M-}&gt;</B> macro also handles formatting. Actually, the
<B>&lt;M-}&gt;</B> macro uses vim's cindent mode to handle the formatting
(which is why it will sometimes do strange things with the curlies,
but normally it gets it right). The beauty is that it also works in
visual mode. If you had:
</P>

<PRE><KBD>
    my_function(  )
    {
	statement1;
	statement2;
	statement3;
	statement4;
	statement5;
	statement6;
	statement7;
    }
</KBD></PRE>

<P>
and you want to put statement3, 4, 5 and 6 in an if block, All you
need to do is type the new if statement over statement3, ie:
</P>

<PRE><KBD>
	statement2;
	if( extra_statements )
	statement3;
</KBD></PRE>

<P>
then highlight the lines which should appear in the new if block, in
this case from <KBD>statement3</KBD> to <KBD>statement6</KBD>, and then type
<B>&lt;M-}&gt;</B>,
you will see something like this:
</P>

<PRE><KBD>
    my_function(  )
    {
	statement1;
	statement2;
	if( extra_statements )
	{
	    statement3;
	    statement4;
	    statement5;
	    statement6;
	}
	statement7;
    }
</KBD></PRE>

<H1>A quick HTML example</H1>
<P>
In HTML things are different once again, there you need a key-word at
the start <EM>and</EM> at the end of most formatting controls. ie: a
heading: <B>&lt;H1&gt;Heading&lt;/H1&gt;</B>. That's easy enough in
insert mode, the <B>word directly before the cursor</B> at the time
you use the <B>&lt;M-h&gt;</B> macro will be used as the HTML tag!
ie: (the cursor position is shown with an <B>_</B> (underscore))
</P>

<CENTER>
<TABLE BORDER=2 CELLPADDING=5 ALIGN=CENTER>
<THEAD>
<TR>
    <TH><B>You type:</B>
    <TH><B>You get:</B>
</TR>
</THEAD>
<TBODY>

<TR>
    <TD>h1<B>&lt;M-h&gt;</B>
    <TD>&lt;H1&gt;<B>_</B>&lt;/H1&gt;<B>&laquo;&raquo;</B>
</TR>

<TR>
    <TD>Heading<B>&lt;Del&gt;</B>
    <TD>&lt;H1&gt;Heading&lt;/H1&gt;<B>_</B>
</TR>

</TBODY>
</TABLE>
</CENTER>

<P>
or, for paragraphs, lists etc, it gets a little complicated, but it's
still easier than typing the whole damn lot per hand :-)
</P>

<CENTER>
<TABLE BORDER=2 CELLPADDING=5 ALIGN=CENTER>
<THEAD>
<TR>
    <TH><B>You type:</B>
    <TH><B>You get:</B>
</TR>
</THEAD>
<TBODY>

<TR>
    <TD>p<B>&lt;M-h&gt;</B>
    <TD>&lt;P&gt;<B>_</B>&lt;/P&gt;<B>&laquo;&raquo;</B>
</TR>

<TR>
    <TD><B>&lt;Return&gt;&lt;Return&gt;&lt;Up&gt;&lt;C-T&gt;</B>
    <TD><PRE>
&lt;P&gt;
    <B>_</B>
&lt;/P&gt;<B>&laquo;&raquo;</B></PRE>
</TR>

</TBODY>
</TABLE>
</CENTER>

<P>
<B>P.S.:</B> &lt;C-T&gt; is vi's way of indenting stuff. Much nicer than
naked Tabs.
</P>

<H2>But there are problems!</H2>
<P>
Sadly! <EM>After the fact</EM> html<EM>ifying</EM> can't (at the
moment) prompt you for a html tag to put at the start and end of the
highlighted text, so you have to do it yourself. Yet another
<EM>what you type isn't what you get</EM> example, lets have some fun
with a disfunctional line:
</P>

<PRE><KBD>
    disfunctional
</KBD></PRE>

<P>
now highlight <B>fun</B> with vim's visual mode commands, and then hit
<B>&lt;M-h&gt;</B>, you get: (cursor position is shown by the
<B>_</B> (underscore))
</P>

<PRE><KBD>
    dis&lt;<B>_</B>&gt;fun&lt;/&laquo;&raquo;&gt;ctional
</KBD></PRE>

<P>
now all you have to do is fill in the tag at the start and the end,
the following keystrokes will now turn the fun on strong:
</P>

<PRE>
    You type: strong&lt;Del&gt;strong&lt;Esc&gt;
    
    You get:  dis&lt;strong&gt;fun&lt;/strong&gt;ctional
</PRE>

<P>
or, as html would show it: dis<STRONG>fun</STRONG>ctional
</P>

<H1>Making your own Forms</H1>
<P>
To create your own forms, use the macro <B>&lt;M-DEL&gt;</B> to insert a new
jump marker. You can type text between the markers, and this
text will be printed on the command line when the user jumps
to that marker. ie:
</P>

<PRE><KBD>
    Name:	<B>&laquo;user's name&raquo;</B>
    Address:	<B>&laquo;user's address&raquo;</B>
    Account:	<B>&laquo;user's bank account number :-)&raquo;</B>
</KBD></PRE>

<P>
For further examples of forms, see the templates/ directory.
</P>

<H1>Signoff</H1>
<P>
Well, you should now have an insight as to how these macros work
together - they are orthogonal, easy to remember, easy to type (if you
have Meta keys) and quite flexible. They are also free, and more or
less unsupported. (if you send me an e-mail I'll probably answer, but
I can't guarantee it!)
</P>

<P>
<B>Bug fixes, suggestions, comments and improvements are all welcome!</B>
</P>

<P><B>Enjoy!</B></P>

<HR>
<ADDRESS>
Stephen Riehm<BR>
e-mail: <A HREF="mailto:Stephen.Riehm@pc-plus.de">Stephen.Riehm@pc-plus.de</A><BR>
</ADDRESS>

<HR>
<CENTER>&copy; Copyright: Stephen Riehm 1991 - 1998</CENTER>

</BODY>
</HTML>
